
#include "RtBase.h"
#include "RtThreadReactor.h"
#include "RtReactorInterface.h"
#include "RtConditionVariable.h"

//////////////////////////////////////////////////////////////////////
// class CRtThreadReactor
//////////////////////////////////////////////////////////////////////

CRtThreadReactor::CRtThreadReactor()
	: m_pReactor(NULL)
#ifdef RT_WIN32_ENABLE_AsyncGetHostByName
	, m_dnsManager(NULL)
#endif
{
}

CRtThreadReactor::~CRtThreadReactor()
{
	delete m_pReactor;
}

RtResult CRtThreadReactor::Init(IRtReactor *aReactor)
{
	RT_ASSERTE_RETURN(!m_pReactor, RT_ERROR_ALREADY_INITIALIZED);
	RT_ASSERTE_RETURN(aReactor, RT_ERROR_INVALID_ARG);
	
	m_pReactor = aReactor;
	return RT_OK;
}

RtResult CRtThreadReactor::
Create(CRtThreadManager::TType aType, CRtThreadManager::TFlag aFlag)
{
	RtResult rv = CRtThread::Create(aType, aFlag);
	if (RT_SUCCEEDED(rv)) {
		// have to open reactor here because main function will do some initial stuffs.
		if (m_Type == CRtThreadManager::TT_MAIN) {
			rv = m_pReactor->Open();
			if (RT_FAILED(rv)) {
				RT_ERROR_TRACE("CRtThreadReactor::OnThreadRun, m_pReactor->Open() failed! rv=" << rv);
			}
		}
	}
	return rv;
}

void CRtThreadReactor::OnThreadInit()
{
	RT_ASSERTE_RETURN_VOID(m_pReactor);

	if (m_Type != CRtThreadManager::TT_MAIN) {
		RtResult rv = m_pReactor->Open();
		if (RT_FAILED(rv)) {
			RT_ERROR_TRACE("CRtThreadReactor::OnThreadInit, m_pReactor->Open() failed! rv=" << rv);
			RT_ASSERTE(FALSE);
		}
	}
}

void CRtThreadReactor::OnThreadRun()
{
	RT_ASSERTE_RETURN_VOID(m_pReactor);
	RT_INFO_TRACE("CRtThreadReactor::OnThreadRun, Begin.");
	
	m_pReactor->RunEventLoop();

	// close the notify avoid Close in other thread .
	// because it will remove handler in the reactor.
	m_pReactor->Close();

#ifdef RT_WIN32_ENABLE_AsyncGetHostByName
	if (m_dnsManager)
	{
		m_dnsManager->DestroyDnsWindow();
		m_dnsManager = NULL;
	}
#endif

	RT_INFO_TRACE("CRtThreadReactor::OnThreadRun, End.");
}

RtResult CRtThreadReactor::Stop(CRtTimeValue* aTimeout)
{
//	RT_ASSERTE_RETURN(!aTimeout, RT_ERROR_NOT_IMPLEMENTED);
	RT_ASSERTE_RETURN(m_pReactor, RT_ERROR_NOT_INITIALIZED);
	m_stopped = TRUE;
	return m_pReactor->StopEventLoop();
}

IRtReactor* CRtThreadReactor::GetReactor()
{
	return m_pReactor;
}

IRtEventQueue* CRtThreadReactor::GetEventQueue()
{
	return m_pReactor;
}

IRtTimerQueue* CRtThreadReactor::GetTimerQueue()
{
	return m_pReactor;
}

//////////////////////////////////////////////////////////////////////
// class CRtThreadDummy
//////////////////////////////////////////////////////////////////////

CRtThreadDummy::CRtThreadDummy()
	: m_pActualThread(NULL)
{
}

CRtThreadDummy::~CRtThreadDummy()
{
}

RtResult CRtThreadDummy::Init(CRtThread *aThread, CRtThreadManager::TType aType)
{
	RT_ASSERTE_RETURN(!m_pActualThread, RT_ERROR_ALREADY_INITIALIZED);
	RT_ASSERTE_RETURN(aThread, RT_ERROR_INVALID_ARG);
	RT_ASSERTE(aThread->GetThreadType() != aType);
	
	m_Type = aType;
	m_Tid = aThread->GetThreadId();
	m_Handle = aThread->GetThreadHandle();
	m_pActualThread = aThread;

	return CRtThreadManager::Instance()->RegisterThread(this);
}

RtResult CRtThreadDummy::
Create(CRtThreadManager::TType aType, CRtThreadManager::TFlag aFlag)
{
	RT_ASSERTE(!"CRtThreadDummy::Create");
	return RT_ERROR_NOT_IMPLEMENTED;
}

RtResult CRtThreadDummy::Stop(CRtTimeValue* aTimeout)
{
	if (m_pActualThread)
		return m_pActualThread->Stop(aTimeout);
	return
		RT_ERROR_NOT_INITIALIZED;
}

void CRtThreadDummy::OnThreadRun()
{
	RT_ASSERTE(!"CRtThreadDummy::OnThreadRun");
}

IRtReactor* CRtThreadDummy::GetReactor()
{
	if (m_pActualThread)
		return m_pActualThread->GetReactor();
	else
		return NULL;
}

IRtEventQueue* CRtThreadDummy::GetEventQueue()
{
	if (m_pActualThread)
		return m_pActualThread->GetEventQueue();
	else
		return NULL;
}

IRtTimerQueue* CRtThreadDummy::GetTimerQueue()
{
	if (m_pActualThread)
		return m_pActualThread->GetTimerQueue();
	else
		return NULL;
}
